home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / plotting / imagetoo / imagetl1.lha / Imagetool / HDF / dfcomp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-09-20  |  15.2 KB  |  517 lines

  1. /*****************************************************************************
  2. *              NCSA HDF version 3.10
  3. *                July 1, 1990
  4. *
  5. * NCSA HDF Version 3.10 source code and documentation are in the public
  6. * domain.  Specifically, we give to the public domain all rights for future
  7. * licensing of the source code, all resale rights, and all publishing rights.
  8. * We ask, but do not require, that the following message be included in all
  9. * derived works:
  10. * Portions developed at the National Center for Supercomputing Applications at
  11. * the University of Illinois at Urbana-Champaign.
  12. * THE UNIVERSITY OF ILLINOIS GIVES NO WARRANTY, EXPRESSED OR IMPLIED, FOR THE
  13. * SOFTWARE AND/OR DOCUMENTATION PROVIDED, INCLUDING, WITHOUT LIMITATION,
  14. * WARRANTY OF MERCHANTABILITY AND WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE
  15. *****************************************************************************/
  16.  
  17. #ifdef RCSID
  18. static char RcsId[] = "@(#)$Revision: 3.2 $";
  19. #endif
  20. /*
  21. $Header: /pita/work/HDF/dev/RCS/src/dfcomp.c,v 3.2 90/07/02 10:12:14 clow beta $
  22.  
  23. $Log:    dfcomp.c,v $
  24.  * Revision 3.2  90/07/02  10:12:14  clow
  25.  * some cosmetic modifications
  26.  * 
  27. */
  28. /*-----------------------------------------------------------------------------
  29.  * File:    dfcomp.c
  30.  * Purpose: File compression
  31.  * Invokes: df.c dfimcomp.c df.h
  32.  * Contents: 
  33.  *  DFputcomp: compress image and write it to HDF file
  34.  *  DFgetcomp: read compressed image from HDF file and decompress it
  35.  *  DFCrle: compress string using run length encoding
  36.  *  DFCunrle: decompress string using run length encoding
  37.  * Remarks: DFgetcomp and DFputcomp constitute a general compression interface
  38.  *---------------------------------------------------------------------------*/
  39.  
  40. #include "df.h"
  41.  
  42. #ifndef VMS
  43. extern void DFCimcomp(), DFCunimcomp();
  44. #else /*VMS*/
  45. extern void _DFCimcomp(), _DFCunimcomp();
  46. #endif
  47.  
  48. /*-----------------------------------------------------------------------------
  49.  * Name:    DFputcomp
  50.  * Purpose: Compress and write images to HDF file
  51.  * Inputs:  dfile: pointer to HDF file
  52.  *          tag, ref: tag, ref of compressed image for writing out
  53.  *          image: image to be compressed
  54.  *          xdim, ydim: dimensions of image
  55.  *          palette: palette associated with image
  56.  *          newpal: modified palette, produced if compression scheme is IMCOMP
  57.  *          scheme: compression scheme to be used
  58.  * Returns: 0 on success, -1 on failure with DFerror set
  59.  * Users:   HDF programmers, DF8putrig, other routines
  60.  * Invokes: DFCrle, DFCimcomp, DFaccess, DFwrite, DFIcheck
  61.  * Remarks: IMCOMP modifies the palette associated with the image
  62.  *          Hence the palette and newpal arguments
  63.  *          This is a general compression interface - to be used anytime image
  64.  *          compression is needed in HDF
  65.  *          Note that rseq does its own compression, because that is part of
  66.  *          the interactive color raster protocol
  67.  *          The space needed for compression and decompression can be allocated
  68.  *          statically or dynamically, depending on the DF_DYNAMIC flag, and
  69.  *          for entire image or part of it (reused) depending on availability
  70.  *          Accordingly, writing out is whole image, or row by row
  71.  *          Note that compression is always row by row for RLE.
  72.  *---------------------------------------------------------------------------*/
  73.  
  74.  
  75. int DFputcomp(dfile, tag, ref, image, xdim, ydim, palette, newpal, scheme)
  76. DF *dfile;
  77. uint16 tag, ref;
  78. char *image;
  79. int32 xdim, ydim;
  80. char *palette, *newpal;
  81. int16 scheme;
  82. {
  83.     char *buffer;        /* buffer to hold compressed image */
  84.     char *in;            /* pointer to input for compression */
  85.     char *out;            /* pointer to space for compressed output */
  86.     int32 cisize;        /* maximum size of compressed image */
  87.     int32 crowsize;        /* maximum size of compressed row */
  88.     int32 buftype;        /* buftype = 1: buffer enough for whole image*/
  89.                 /* buftype = 2: buffer holds 1 row */
  90.     int32 n;            /* number of compressed bytes produced */
  91.     int32 total;        /* total compressed bytes produced so far */
  92.     int i, ret=0;
  93.  
  94.     if (DFIcheck(dfile)<0) return(-1);
  95.     if (!tag) {
  96.         DFerror = DFE_BADTAG;
  97.         return(-1);
  98.     }
  99.     if (!ref) {
  100.         DFerror = DFE_BADREF;
  101.         return(-1);
  102.     }
  103.     if ((xdim<=0) || (ydim<=0)) {
  104.         DFerror = DFE_BADDIM;
  105.         return(-1);
  106.     }
  107.     if (!image) {
  108.         DFerror = DFE_BADPTR;
  109.         return(-1);
  110.     }
  111.  
  112.     if (DFaccess(dfile, tag, ref, "w")<0) return(-1); /* setup to write CI */
  113.  
  114.     switch (scheme) {
  115.       case DFTAG_RLE:
  116.     cisize = ydim*(xdim*121/120+1);    /* 120 chars can compress to 121! */
  117.     crowsize = xdim*121/120 + 128;
  118.  
  119.     /* allocate buffer for compression */
  120. #ifdef DF_DYNAMIC        /* large mallocs OK */
  121.     buffer = (char *) DFIgetspace((unsigned)cisize);
  122.     if (!buffer) {
  123.         buffer = (char *) DFIgetspace((unsigned)crowsize);
  124.         if (!buffer) {
  125.         DFerror = DFE_NOSPACE;
  126.         return(-1);
  127.         }
  128.         buftype = 2;    /* compress and write out row by row */
  129.     }
  130.     else buftype = 1;       /* can hold whole image, then write */
  131.  
  132. #else /*DF_DYNAMIC                    use static buffers */
  133.     buffer = DFtbuf;
  134.     if (DF_TBUFSZ>=cisize) buftype = 1;
  135.     else if (DF_TBUFSZ>crowsize) buftype = 2;
  136.     else {
  137.         DFerror = DFE_NOSPACE;
  138.         return(-1);
  139.     }
  140. #endif /*DF_DYNAMIC*/
  141.  
  142.     in = image;
  143.     out = buffer;
  144.     n = total = 0;        /* no bytes compressed so far */
  145.  
  146.     /* compress row by row */
  147.     for (i=0; i<ydim; i++) {
  148.         n = DFCrle(in, out, xdim); /* compress row */
  149.         in += xdim;        /* move input pointer */
  150.         total += n;        /* keep running total */
  151.         if (buftype==1)    /* can hold whole image */
  152.         out = &buffer[total]; /* move out buffer pointer */
  153.         else {        /* buffer too small, */
  154.                 /* write out what was produced */
  155.         if (DFwrite(dfile, buffer, n)<0) {
  156.             ret = -1;    /* flag value */
  157.             break;
  158.         }
  159.         out = buffer;    /* reset output pointer */
  160.         }
  161.     }
  162.  
  163.     if (buftype==1)        /* write out entire image */
  164.                 ret = DFwrite(dfile, buffer, total);
  165.     break;
  166.  
  167.       case DFTAG_IMC:
  168.         if (!palette || !newpal) { /* need palette and newpal */
  169.             DFerror = DFE_BADPTR;
  170.             return(-1);
  171.         }
  172.         cisize = xdim*ydim/4;    /* IMCOMP always cuts to 1/4 */
  173.  
  174. #ifdef DF_DYNAMIC
  175.         buffer = (char *) DFIgetspace((unsigned)cisize);
  176.         if (!buffer) {
  177.             DFerror = DFE_NOSPACE;
  178.             return(-1);
  179.         }
  180. #else /*DF_DYNAMIC*/
  181.         if (DF_TBUFSZ<cisize) {
  182.             DFerror = DFE_NOSPACE;
  183.             return(-1);
  184.         }
  185.         buffer = DFtbuf;
  186. #endif /*DF_DYNAMIC*/
  187.  
  188.         DFCimcomp(xdim, ydim, image, buffer, palette, newpal, 0);
  189.         ret = DFwrite(dfile, buffer, cisize);
  190.         break;
  191.  
  192.     default:            /* unknown compression scheme */
  193.         DFerror = DFE_BADSCHEME;
  194.         return(-1);
  195.         break;
  196.     }
  197. #ifdef DF_DYNAMIC
  198.     DFIfreespace((char*)buffer);
  199. #endif /*DF_DYNAMIC*/
  200.     return(ret);
  201. }
  202.  
  203. /*-----------------------------------------------------------------------------
  204.  * Name:    DFgetcomp
  205.  * Purpose: Read compressed image and decompress it
  206.  * Inputs:  dfile: HDF file pointer
  207.  *          tag, ref: id of image to be decompressed
  208.  *          image: space to return decompressed image in
  209.  *          xdim, ydim: dimensions of decompressed image
  210.  *          scheme: compression scheme used
  211.  * Returns: 0 on success, -1 on failure with DFerror set
  212.  * Users:   HDF programmers, DF8getrig, other routines
  213.  * Invokes: DFIcheck, DFIfind, DFaccess, DFread, DFCunrle, DFCunimcomp
  214.  * Remarks: Will use dynamic/static memory allocation for buffer
  215.  *          will read in image in parts if memory insufficient
  216.  *          Decompression of rle is not necessarily row by row
  217.  *          Other encodings can also be decoded with this
  218.  *---------------------------------------------------------------------------*/
  219.  
  220. int DFgetcomp(dfile, tag, ref, image, xdim, ydim, scheme)
  221. DF *dfile;
  222. uint16 tag, ref;
  223. char *image;
  224. int32 xdim, ydim;
  225. uint16 scheme;
  226. {
  227.     char *buffer, *in, *out;
  228.     int32 cisize, crowsize, buflen, bufleft; /* bufleft: bytes left in buffer*/
  229.     DFdle *dlep;
  230.     int cdd, i, n, totalread;
  231.  
  232.     if (DFIcheck(dfile)<0) return(-1);
  233.     if (!tag) {
  234.         DFerror = DFE_BADTAG;
  235.         return(-1);
  236.     }
  237.     if (!ref) {
  238.         DFerror = DFE_BADREF;
  239.         return(-1);
  240.     }
  241.     if (!image) {
  242.         DFerror = DFE_BADPTR;
  243.         return(-1);
  244.     }
  245.     if ((xdim<=0) || (ydim<=0)) {
  246.         DFerror = DFE_BADDIM;
  247.         return(-1);
  248.     }
  249.  
  250.     if (DFIfind(dfile, tag, ref, 1, 0, 0, &dlep, &cdd)<0) {
  251.         DFerror = DFE_NOMATCH;
  252.         return(-1);
  253.     }
  254.     cisize = dlep->dd[cdd].length;
  255.  
  256.     if (DFaccess(dfile, tag, ref, "r")<0) return(-1);
  257.     switch (scheme) {
  258.       case DFTAG_RLE:
  259.     crowsize = xdim*121/120 + 128; /* max size of a row */
  260.  
  261. #ifdef DF_DYNAMIC
  262.     buffer = (char *) DFIgetspace((unsigned)cisize);
  263.     if (!buffer) {
  264.         buffer = (char *) DFIgetspace((unsigned)crowsize);
  265.         if (!buffer) {
  266.         DFerror = DFE_NOSPACE;
  267.         return(-1);
  268.         }
  269.         buflen = crowsize;
  270.     }
  271.     else buflen = cisize;
  272. #else /*DF_DYNAMIC*/
  273.     if (DF_TBUFSZ<crowsize) {
  274.         DFerror = DFE_NOSPACE;
  275.         return(-1);
  276.     }
  277.     buffer = DFtbuf;    /* static compression buffer */
  278.     buflen = DF_TBUFSZ;
  279. #endif /*DF_DYNAMIC*/
  280.  
  281.     in = buffer;
  282.     out = image;
  283.     if ((n=DFread(dfile, in, buflen))<0) {
  284. #ifdef DF_DYNAMIC
  285.         DFIfreespace((char*)buffer);
  286. #endif /*DF_DYNAMIC*/
  287.         return(-1);
  288.     }
  289.     totalread = n;
  290.     bufleft = n;
  291.     for (i=0; i<ydim; i++) {
  292.         n = DFCunrle(in, out, xdim, !i); /* no of bytes used up */
  293.         /* last arg=TRUE if i=0 - resets decompress */
  294.         in += n;
  295.         out += xdim;
  296.         bufleft -= n;
  297.         /* check if more bytes may be needed for next read */
  298.         if ((bufleft<crowsize) && (totalread<cisize)) {
  299.         DFmovmem(in, buffer, (int)bufleft);
  300.         in = buffer;
  301.         if ((n=DFread(dfile,&in[bufleft],buflen-bufleft))<0) {
  302. #ifdef DF_DYNAMIC
  303.             DFIfreespace((char*)buffer);
  304. #endif /*DF_DYNAMIC   */
  305.             return(-1);
  306.         }
  307.         totalread += n;
  308.         bufleft += n;
  309.         }
  310.     }
  311.     break;
  312.  
  313.       case DFTAG_IMC:
  314.     crowsize = xdim;    /* size of compressed row */
  315.  
  316. #ifdef DF_DYNAMIC
  317.     buffer = (char *) DFIgetspace((unsigned)cisize);
  318.     if (!buffer) {
  319.         buffer = (char *) DFIgetspace((unsigned)crowsize);
  320.         if (!buffer) {
  321.         DFerror = DFE_NOSPACE;
  322.         return(-1);
  323.         }
  324.         buflen = crowsize;
  325.     }
  326.     else buflen = cisize;
  327. #else /*DF_DYNAMIC*/
  328.     buffer = DFtbuf;    /* static compression buffer */
  329.     if (DF_TBUFSZ<crowsize) {
  330.         DFerror = DFE_NOSPACE;
  331.         return(-1);
  332.     }
  333.     buflen = DF_TBUFSZ;
  334. #endif /*DF_DYNAMIC*/
  335.     if (buflen>=cisize) {
  336.         if (DFread(dfile, buffer, cisize)<cisize) {
  337. #ifdef DF_DYNAMIC
  338.         DFIfreespace((char*)buffer);
  339. #endif /*DF_DYNAMIC*/
  340.         return(-1);
  341.         }
  342.         DFCunimcomp(xdim, ydim, buffer, image);
  343.         break;        /* go to end of switch */
  344.     }
  345.  
  346.     in = buffer;        /* if can only read piecemeal */
  347.     out = image;
  348.     if ((n=DFread(dfile, in, buflen))<0) {
  349. #ifdef DF_DYNAMIC
  350.         DFIfreespace((char*)buffer);
  351. #endif /*DF_DYNAMIC*/
  352.         return(-1);
  353.     }
  354.     totalread = n;
  355.     bufleft = n;
  356.     for (i=0; i<ydim; i+=4) {
  357.         DFCunimcomp(xdim, (int32)4, in, out);
  358.         in += xdim;
  359.         out += 4*xdim;
  360.         bufleft -= xdim;
  361.         if ((bufleft<crowsize) && (totalread<cisize)) {
  362.         DFmovmem(in, buffer, (int)bufleft);
  363.         in = buffer;
  364.         if ((n=DFread(dfile,&in[bufleft],buflen-bufleft))<0) {
  365. #ifdef DF_DYNAMIC
  366.             DFIfreespace((char*)buffer);
  367. #endif /*DF_DYNAMIC*/
  368.             return(-1);
  369.         }
  370.         totalread += n;
  371.         bufleft += n;
  372.         }
  373.     }
  374.     break;
  375.  
  376.       default:            /* unknown scheme */
  377.     DFerror = DFE_BADSCHEME;
  378.     return(-1);
  379.     break;
  380.     }
  381. #ifdef DF_DYNAMIC
  382.     DFIfreespace((char*)buffer);
  383. #endif /*DF_DYNAMIC*/
  384.     return(0);
  385. }
  386.  
  387. /*-----------------------------------------------------------------------------
  388.  * Name:    DFCrle
  389.  * Purpose: compress a string of bytes
  390.  * Inputs:  buf: buffer containing data to be compressed
  391.  *          bufto: space for compressed data - assumed big enough
  392.  *          len: number of bytes to compress
  393.  * Returns: number of compressed bytes on success, -1 on failure
  394.  * Users:   HDF programmers, DFputcomp, other routines
  395.  * Invokes: none
  396.  * Remarks: Written for efficiency
  397.  *---------------------------------------------------------------------------*/
  398.  
  399. int DFCrle(buf,bufto,len)
  400. int32 len;
  401. char *buf,*bufto;
  402. {
  403.     register char *p,*q,*cfoll,*clead;
  404.     char *begp;
  405.     int32 i;
  406.  
  407.     p = buf;
  408.     cfoll = bufto;        /* place to copy to */
  409.     clead = cfoll + 1;
  410.     
  411.     begp = p;
  412.     while (len > 0) {           /* encode stuff until gone */
  413.  
  414.         q = p + 1;
  415.         i = len-1;
  416.         while (i && i+120 > len && *p == *q) {
  417.             q++;
  418.             i--;
  419.         }
  420.         
  421.         if (q > p + 2) {        /* three in a row */
  422.             if (p > begp) {
  423.                 *cfoll = p - begp;
  424.                 cfoll = clead;
  425.             }
  426.             *cfoll++ = 128 | (q-p); /* len of seq */
  427.             *cfoll++ = *p;      /* char of seq */
  428.             len -= q-p;         /* subtract len of seq */
  429.             p = q;
  430.             clead = cfoll+1;
  431.             begp = p;
  432.         }
  433.         else {
  434.             *clead++ = *p++;    /* copy one char */
  435.             len--;
  436.             if (p > begp + 120) {
  437.                 *cfoll = p - begp;
  438.                 cfoll = clead++;
  439.                 begp = p;
  440.             }
  441.         }
  442.         
  443.     }
  444. /*
  445.  *  fill in last bytecount
  446.  */
  447.     if (p > begp) 
  448.         *cfoll = (p - begp);
  449.     else
  450.         clead--;                    /* don't need count position */
  451.     
  452.     return((int)(clead - bufto));   /* how many stored as encoded */
  453. }
  454.  
  455. /*-----------------------------------------------------------------------------
  456.  * Name:    DFCunrle
  457.  * Purpose: decompress run length encoding
  458.  * Inputs:  buf: buffer containing compressed data
  459.  *          bufto: space for returning decompressed data
  460.  *          outlen: number of *decompressed* bytes desired.
  461.  *          resetsave: don't use any stored state info - used for fresh image
  462.  * Returns: number of compressed bytes used up on success, -1 on failure
  463.  * Users:   HDF programmers, DFgetcomp, other routines
  464.  * Invokes: none
  465.  * Remarks: has been modified so it will decompress even non-rowwise compression
  466.  *          Hence the static storage stuff
  467.  *---------------------------------------------------------------------------*/
  468.  
  469. int DFCunrle(buf,bufto,outlen, resetsave)
  470. int32 outlen;
  471. char *buf,*bufto;
  472. int resetsave;
  473. {
  474.     register int cnt;
  475.     register char *p,*q;
  476.     char *endp;
  477.     static char save[255], *savestart=NULL, *saveend=NULL;
  478.     /* save has a list of decompressed bytes not returned in
  479.        previous call.  savestart and saveend specify the position
  480.        at which this list starts and ends in the array save */
  481.     
  482.     p = buf;
  483.     endp = bufto + outlen;
  484.     q = bufto;
  485.     if (resetsave) savestart = saveend = save; /* forget saved state */
  486.     while ((saveend>savestart) && (q<endp)) /* copy saved stuff */
  487.         *q++ = *savestart++;
  488.     if (savestart>=saveend) savestart = saveend = save;    /* all copied */
  489.     while (q < endp) {
  490.         cnt = *p++;        /* count field */
  491.         if (!(cnt & 128)) {    /* is set of uniques */
  492.             while (cnt--) {
  493.                 if (q<endp)
  494.                     *q++ = *p++; /* copy unmodified */
  495.                 else
  496.                     *saveend++ = *p++;
  497.             }
  498.         }
  499.         else {
  500.             cnt &= 127;        /* strip high bit */
  501.             while (cnt--) {
  502.                 if (q<endp)
  503.                     *q++ = *p;  /* copy unmodified */
  504.                 else
  505.                     *saveend++ = *p;
  506.             }
  507.             p++;                /* skip that character */
  508.         }
  509.     }
  510.     return((int)(p-buf));
  511. }
  512.